package eerbaar.shared.persist.internal.lib;

import java.util.List;

import eerbaar.level.IComplete;
import eerbaar.level.IHints;
import eerbaar.level.ILevel;
import eerbaar.level.IMessages;
import eerbaar.level.IStartup;
import eerbaar.level.IStates;
import eerbaar.level.LevelFactory;
import eerbaar.shared.exceptions.GameException;
import eerbaar.shared.exceptions.GameRuntimeException;
import eerbaar.shared.persist.IPersistService;
import eerbaar.shared.persist.IPersister;
import eerbaar.shared.persist.ISaver;
import eerbaar.shared.service.ServiceFactory;
import eerbaar.shared.tree.IAttributes;
import eerbaar.shared.tree.INode;
import eerbaar.shared.tree.NodeCmdFactory;

public class LevelPersister implements IPersister<ILevel> {

    public static final String NAME = "level";

    private ILevel target;

    public LevelPersister() {
        //
    }

    public LevelPersister(ILevel target) {
        this.target = target;
    }

    public LevelPersister(INode node) throws GameRuntimeException {
        load(node);
    }

    @Override
    public Class<ILevel> getRegistertedInterface() {
        return ILevel.class;
    }

    @Override
    public ISaver<?>[] getSavableChildren() {

        StartupPersister s = new StartupPersister(this.target.getStartup());
        MessagesPersister m = new MessagesPersister(this.target.getMessages());
        CompletePersister c = new CompletePersister(this.target.getComplete());
        StatesPersister ss = new StatesPersister(this.target.getStates());
        HintsPersister h = new HintsPersister(this.target.getHints());
        return new ISaver<?>[] { s, m, c, ss, h };
    }

    @Override
    public String getSavableName() {

        return NAME;
    }

    @Override
    public ILevel getTarget() {

        return this.target;
    }

    @Override
    public boolean isAssignableFrom(ISaver<?> saver) {

        return false;
    }

    @Override
    public ILevel load(INode node) {
        assert (node != null);

        IAttributes a = node.getAttributes();

        int index = a.get(Integer.class, "index");
        String goal = a.get(String.class, "goal");
        ILevel result = LevelFactory.create(index, goal);

        IStartup s = load(node, StartupPersister.NAME, IStartup.class);
        result.setStartup(s);

        IMessages m = load(node, MessagesPersister.NAME, IMessages.class);
        result.setMessages(m);

        IComplete c = load(node, CompletePersister.NAME, IComplete.class);
        result.setComplete(c);

        IStates ss = load(node, StatesPersister.NAME, IStates.class);
        result.setStates(ss);

        IHints h = load(node, HintsPersister.NAME, IHints.class);
        result.setHints(h);

        return result;
    }

    private <T> T load(INode node, String name, Class<T> type) {

        IPersistService service = ServiceFactory
                .getService(IPersistService.class);

        List<INode> list = NodeCmdFactory.findChildren(node, name);
        for (INode n : list) {
            try {
                T obj = service.load(type, n);
                return obj;
            } catch (GameException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    @Override
    public void saveAttributes(INode node) {

        IAttributes a = node.getAttributes();

        int index = this.target.getIndex();
        a.set(Integer.class, "index", index);

        String goal = this.target.getGoal();
        a.set(String.class, "goal", goal);
    }

    @Override
    public void setTarget(ILevel obj) {

        this.target = obj;
    }

}
